﻿using Canteen.Core.Common;
using StackExchange.Redis;
using System;
using System.Threading.Tasks;

namespace Canteen.Core.Services
{
    public class WechatServiceImplement : IWechatService
    {
        #region 构造函数
        private readonly IRedisCacheManager _redisCacheManager;
        private readonly IWechat _wechat;

        //public WechatGzhOptions Options => throw new NotImplementedException();
        public WechatGzhOptions Options { get; private set; }

        public WechatServiceImplement(IRedisCacheManager redisCacheManager, IWechat wechat)
        {
            _redisCacheManager = redisCacheManager;
            _wechat = wechat;
            Options = wechat.Options;
        }
        #endregion

        #region 私有函数
        private T RedisCache<T>(Func<IDatabase, T> func)
        {
            return func(_redisCacheManager.RedisCache(c => c, 7));
        }
        #endregion

        public async Task<string> GetAccessTokenAsync()
        {
            const string AccessTokenKey = "access_token:client_credential";
            var cache = RedisCache(c => c);
            if (await cache.KeyExistsAsync(AccessTokenKey)) return await cache.StringGetAsync(AccessTokenKey);
            var accessToken = await _wechat.RequestWechatGzhAccessTokenAsync();
            if(await cache.StringSetAsync(AccessTokenKey, accessToken.access_token, TimeSpan.FromSeconds(accessToken.expires_in)))
            {
                return accessToken.access_token;
            }
            else throw new Exception("保存缓存失败");
        }

        public async Task<string> GetAuthAccessTokenAsync(string Code)
        {
            const string AccessTokenKey = "access_token:authorization_code";
            var cache = RedisCache(c => c);
            if (await cache.KeyExistsAsync(AccessTokenKey)) return await cache.StringGetAsync(AccessTokenKey);
            var accessToken = await _wechat.RequestWechatGzhAuthAccessTokenAsync(Code);
            if (await cache.StringSetAsync(AccessTokenKey, accessToken.access_token, TimeSpan.FromSeconds(accessToken.expires_in)))
            {
                return accessToken.access_token;
            }
            else throw new Exception("保存缓存失败");
        }

        public async Task<string> GetJSAPITicket()
        {
            const string TicketKey = "jsapi_ticket";
            var cache = RedisCache(c => c);
            if (await cache.KeyExistsAsync(TicketKey)) return await cache.StringGetAsync(TicketKey);
            var accessToken = await GetAccessTokenAsync();
            var ticket = await _wechat.RequestWechatGzhJSAPITicket(accessToken);

            if (await cache.StringSetAsync(TicketKey, ticket.ticket, TimeSpan.FromSeconds(ticket.expires_in)))
            {
                return ticket.ticket;
            }
            else throw new Exception("保存缓存失败");
        }
    }
}
